﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.IO;
using System.Linq;
using System.Threading;

namespace ROOTFileSizeAnalyzer.Parsers
{
    public static class LineSource
    {
        /// <summary>
        /// Starting from a string, create an observable that shoots
        /// things at a recvr.
        /// </summary>
        /// <param name="inputFile"></param>
        /// <returns></returns>
        public static IObservable<string> ToLineObservable(this string inputFile)
        {
            return Observable.Create<string>(
                observer =>
                {
                    bool cancel = false;
                    ThreadPool.QueueUserWorkItem(o =>
                    {
                        using (StringReader rdr = new StringReader(inputFile))
                        {
                            string line = null;
                            do
                            {
                                line = rdr.ReadLine();
                                if (line != null)
                                {
                                    observer.OnNext(line);
                                }
                            } while (line != null && !cancel);
                        }

                        observer.OnCompleted();

                    });

                    return () => { cancel = true; };
                }
            );
        }

        /// <summary>
        /// Read a URI async and shoot the items as something that is listening for them.
        /// The thread that OpenReadCompleted comes back on might be the UI thread - so we need
        /// to make sure this is in teh background. If the web read is particularly long, well, then
        /// we need to send stuff off to a background thread - b/c the stream reader can block, and
        /// we don't want to do that on the MainThread!
        /// </summary>
        /// <param name="inputUri"></param>
        /// <returns></returns>
        public static IObservable<string> ToLineObservable(this Uri inputUri)
        {
            return Observable.Create<string>(
                observer =>
                {
                    WebClient cli = new WebClient();
                    cli.OpenReadCompleted += (o, p) =>
                    {
                        ThreadPool.QueueUserWorkItem(oIgnore =>
                            {
                                if (p.Error != null)
                                {
                                    observer.OnError(p.Error);
                                    return;
                                }
                                if (p.Cancelled)
                                {
                                    observer.OnError(new Exception("Read of uri was canceled"));
                                    return;
                                }

                                try
                                {
                                    using (var rdr = new StreamReader(p.Result))
                                    {
                                        while (!rdr.EndOfStream)
                                        {
                                            observer.OnNext(rdr.ReadLine());
                                        }
                                    }
                                }
                                finally
                                {
                                    p.Result.Close();
                                }
                                observer.OnCompleted();
                            });
                    };

                    cli.OpenReadAsync(inputUri);
                    return () => { cli.CancelAsync(); };
                }
            );
        }

    }
}
